package feizhou.untils.tools.json.bean;

/**
 * @ClassName: MultiLayerMap
 * @Description 请描述下该类是做什么的
 * @Author feizhou
 * @Date 2023/10/13  15:55
 * @Verson 1.0
 **/

import com.fasterxml.jackson.databind.JsonNode;
import feizhou.untils.tools.ArrayUtil;
import feizhou.untils.tools.StringUtil;
import feizhou.untils.tools.json.JSONUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 构建json
 *
 * @author <a href="920786312@qq.com">周飞</a>
 * @since 2023/10/13 14:19
 */
@Setter
@ToString
@Getter
public class JsonNodeBean {
    //定义容器
    static Map<String, FieldMappingTree> containerMap = new ConcurrentHashMap<>();

    /**
     * 将json 按照规则，转换为MAP
     * 注意：json不能为数组
     *
     * @param srvJson           原始数据
     * @param fieldMappingTrees 映射节点树
     * @return java.util.Map
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/11/10 11:45
     */
    public static Map<String, Object> buildMap(JsonNode srvJson, List<FieldMappingTree> fieldMappingTrees) {
        // 构建最初map
        Map<String, Object> map = new HashMap();
        buildMap(srvJson, fieldMappingTrees, map, null);
        return map;
    }


    /**
     * 通过递归，构建MAP
     * 这是一个递归方法，
     *
     * @param srvJson           原始数据
     * @param fieldMappingTrees 映射节点树
     * @param map               map数据
     * @param parentTree        父映射节点
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/11/10 11:47
     */
    private static void buildMap(JsonNode srvJson, List<FieldMappingTree> fieldMappingTrees, Map<String, Object> map, FieldMappingTree parentTree) {


        if (srvJson != null && srvJson.isArray()) {//如果数据是数组，也就是 arrayNode, 相当于List<Map>,构建list
            //构建list
            List<Map> list = new ArrayList();
            //父节点名称
            String fieldName = parentTree.getFieldName();
            //构建map的list节点
            map.put(fieldName, list);
            //递归数组元素
            srvJson.forEach(e -> {
                //创建list中的MAP元素
                Map<String, Object> newMap = new HashMap();
                //添加到MAP中
                list.add(newMap);
                //递归下去
                buildMap(e, fieldMappingTrees, newMap, null);
            });
            return; //跳出方法
        }
        //srvJson 不是数组的场景，这个时候srvJson是 objectJSON对象，相当于map

        //递归遍历objectJSON对象里面数据
        for (FieldMappingTree fieldMappingTree : fieldMappingTrees) {

            //获取子节点
            List<FieldMappingTree> childNodes = fieldMappingTree.getChildNodes();
            //获取字段名称
            String fieldName = fieldMappingTree.getFieldName();
            //获取映射字段名称
            String mappingFieldName = fieldMappingTree.getMappingFieldName();

            //递归
            if (childNodes != null) {
                //通过映射字段获取下一个节点
                JsonNode arrayJson = getSonNode(srvJson, mappingFieldName);
                if (arrayJson.isArray()) {//是列表的的话，map，传下去
                    buildMap(arrayJson, childNodes, map, fieldMappingTree);
                } else {
                    // 创建map中map元素
                    Map<String, Object> newMap = new HashMap();
                    //获取数组节点
                    map.put(fieldName, newMap);
                    buildMap(arrayJson, childNodes, newMap, fieldMappingTree);
                }
            } else {
                //当前当前不是数组的场景，获取值
//                JsonNode jsonNode = getSonNode(srvJson, mappingFieldName);
//                String value = jsonNode.asText();
                Object value = buildValue(srvJson, fieldMappingTree);
                map.put(fieldName, value);
            }
        }

    }

    /**
     * 通过映射字段获取下一个节点
     * 如果映射字段为null,返回当前节点
     *
     * @param srvJson
     * @param mappingFieldName
     * @return com.fasterxml.jackson.databind.JsonNode
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/11/10 12:21
     */
    private static JsonNode getSonNode(JsonNode srvJson, String mappingFieldName) {
        if (mappingFieldName == null) {
            return srvJson;
        }
        String[] mappingFieldNameArr = mappingFieldName.split("\\.");
        JsonNode jsonNode = srvJson;

        //mappingFieldName 是多个节点的场景，比如 user.id
        for (int i = 0; i < mappingFieldNameArr.length; i++) {
            jsonNode = jsonNode.get(mappingFieldNameArr[i]);
        }
        return jsonNode;
    }


    /**
     * FieldMappingBean 转 FieldMappingTree
     *
     * @param fieldMappingBeans
     * @return java.util.List<feizhou.untils.tools.json.bean.FieldMappingTree>
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/11/10 14:52
     */
    public static List<FieldMappingTree> toFieldMappingTree(List<FieldMappingBean> fieldMappingBeans) {

        containerMap.clear();//清空容器
        Collections.sort(fieldMappingBeans);//按照层级排序

        //定义映射字段树
        List<FieldMappingTree> fieldMappingTrees = new ArrayList<>();


        for (FieldMappingBean fieldMappingBean : fieldMappingBeans) {
            //构建映射树
            FieldMappingTree tree = buildTree(fieldMappingBean);
            //添加到返回的列表中
            if (!fieldMappingTrees.contains(tree)) {
                fieldMappingTrees.add(tree);
            }
        }
        return fieldMappingTrees;
    }


    private static FieldMappingTree buildTree(FieldMappingBean fieldMappingBean) {

        //不管在不在，先构建一层
        FieldMappingTree treeTemp = fieldMappingBean.buildFieldMappingTree(containerMap);

        //看看容器有没有，没有就加入
        FieldMappingTree tree = containerMap.get(treeTemp.getFullPathName());
        if (tree == null) {
            tree = treeTemp;
            containerMap.put(tree.getFullPathName(), tree);
        }
        //递归
        buildTree(tree, fieldMappingBean);
        return tree;


    }

    private static void buildTree(FieldMappingTree tree, FieldMappingBean fieldMappingBean) {

        if (fieldMappingBean.getFieldLevel() > 0) {
            FieldMappingTree tempSontree = fieldMappingBean.buildFieldMappingTree(containerMap);
            FieldMappingTree sonTree = containerMap.get(tempSontree.getFullPathName());
            if (sonTree == null) {
                sonTree = tempSontree;
                tree.add(sonTree);
                containerMap.put(sonTree.getFullPathName(), sonTree);
            }
            buildTree(sonTree, fieldMappingBean);

        }

    }

    /**
     * 构建值
     * 值（V）的优先级从高到低如下：
     * 1. 策略
     * 2. json里面的值
     * 3. 默认值
     *
     * @param fieldMappingTree 字段映射配置
     * @param srvJson          值的json
     * @return java.lang.String  案例：people.user.name=张三
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/13 19:09
     */
    private static Object buildValue(JsonNode srvJson, FieldMappingTree fieldMappingTree) {

        //获取映射字段名称
        String mappingFieldName = fieldMappingTree.getMappingFieldName();

        //默认值
        String fieldDefaultValue = fieldMappingTree.getFieldDefaultValue();
        //映射字段值处理策略
        FieldStrategy fieldStrategy = fieldMappingTree.getFieldStrategy();


        //获取叶子节点的值
        String value = null;
        if (StringUtil.isNotEmpty(mappingFieldName)) {
            JsonNode jsonNode = getSonNode(srvJson, mappingFieldName);
            if (jsonNode != null) {
                value = jsonNode.asText();
            }

        }


        //值优先级：1. 策略
        if (fieldStrategy != null) {
            //映射字段值处理策略
            return fieldStrategy.execute(value);
        }

        //值优先级：2. json里面的值
        if (StringUtil.isNotEmpty(value)) {
            return value;
        }
        //值优先级：3. 默认值
        if (StringUtil.isNotEmpty(fieldDefaultValue)) {
            return valueConver(fieldDefaultValue, fieldMappingTree.getFieldFormat());
        }
        return null;
    }

    /**
     * 值转换
     *
     * @param value            值
     * @param fieldFormat：转换格式
     * @return java.lang.Object
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/11/30 14:49
     */
    private static Object valueConver(String value, String fieldFormat) {

        if (StringUtil.isEmpty(value)) {//排查空情况
            return null;
        }

        if (EnumFieldFormat.getFieldFormat(fieldFormat) == EnumFieldFormat.jsonObject) {
            return value;
        }
        if (EnumFieldFormat.getFieldFormat(fieldFormat) == EnumFieldFormat.jsonArray) {

            if ("[]".equals(value)) {//空数组的场景
                return new ArrayList<>();
            }
            String[] arrValue = value.split(",");
            return Arrays.asList(arrValue);
        }
        return value;

    }

    public static void main(String[] args) throws Exception {

//        String jsonStr = "{ \"result\": { \"list\": [ { \"id\": \"3160526161138725025\", \"subject\": \"深圳市晨光乳业低温奶经销合同\", \"description\": \"\", \"sn\": \"202311100000010\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3157957724801716803\", \"name\": \"经销商低温合同\" }, \"status\": \"FILLING\", \"expireTime\": \"2023-12-10 00:00:00\", \"publishTime\": \"2023-11-10 17:22:57\" }, { \"id\": \"3160522340568138470\", \"subject\": \"深圳市晨光乳业低温奶经销合同\", \"description\": \"\", \"sn\": \"202311100000009\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3157957724801716803\", \"name\": \"经销商低温合同\" }, \"status\": \"COMPLETE\", \"expireTime\": \"2023-12-10 00:00:00\", \"publishTime\": \"2023-11-10 17:07:45\" }, { \"id\": \"3160509736579834270\", \"subject\": \"深圳市晨光乳业低温奶经销合同\", \"description\": \"\", \"sn\": \"202311100000008\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3157957724801716803\", \"name\": \"经销商低温合同\" }, \"status\": \"DRAFT\", \"expireTime\": \"2023-12-10 00:00:00\" }, { \"id\": \"3160507622377988199\", \"subject\": \"深圳市晨光乳业低温奶经销合同\", \"description\": \"\", \"sn\": \"202311100000007\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3157957724801716803\", \"name\": \"经销商低温合同\" }, \"status\": \"SIGNING\", \"expireTime\": \"2023-12-10 00:00:00\", \"publishTime\": \"2023-11-10 16:09:16\" }, { \"id\": \"3160441723923039080\", \"subject\": \"深圳市晨光乳业低温奶经销合同\", \"description\": \"\", \"sn\": \"202311100000006\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3157957724801716803\", \"name\": \"经销商低温合同\" }, \"status\": \"SIGNING\", \"expireTime\": \"2023-12-10 00:00:00\", \"publishTime\": \"2023-11-10 11:49:34\" }, { \"id\": \"3160438936279495203\", \"subject\": \"深圳市晨光乳业低温奶经销合同\", \"description\": \"\", \"sn\": \"202311100000005\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3157957724801716803\", \"name\": \"经销商低温合同\" }, \"status\": \"SIGNING\", \"expireTime\": \"2023-12-10 00:00:00\", \"publishTime\": \"2023-11-10 11:36:16\" }, { \"id\": \"3160436674241016125\", \"subject\": \"深圳市晨光乳业低温奶经销合同\", \"description\": \"\", \"sn\": \"202311100000004\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3157957724801716803\", \"name\": \"经销商低温合同\" }, \"status\": \"SIGNING\", \"expireTime\": \"2023-12-10 00:00:00\", \"publishTime\": \"2023-11-10 11:27:23\" }, { \"id\": \"3160434826402693132\", \"subject\": \"深圳市晨光乳业低温奶经销合同\", \"description\": \"\", \"sn\": \"202311100000003\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3157957724801716803\", \"name\": \"经销商低温合同\" }, \"status\": \"RECALLED\", \"expireTime\": \"2023-12-10 00:00:00\", \"publishTime\": \"2023-11-10 11:21:14\" }, { \"id\": \"3160402148504679418\", \"subject\": \"2022年低温奶经销合同(经销商版本)(2)(1)\", \"description\": \"\", \"sn\": \"202311100000002\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3157957724801716803\", \"name\": \"经销商低温合同\" }, \"status\": \"DRAFT\", \"expireTime\": \"2023-12-10 00:00:00\" }, { \"id\": \"3160164492193661834\", \"subject\": \"测试\", \"description\": \"\", \"sn\": \"202311090000001\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3157957724801716803\", \"name\": \"经销商低温合同\" }, \"status\": \"SIGNING\", \"expireTime\": \"2023-12-09 00:00:00\", \"publishTime\": \"2023-11-09 17:26:40\" }, { \"id\": \"3157607247824073189\", \"subject\": \"测试\", \"description\": \"\", \"sn\": \"202311020000002\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3151379140272197664\", \"name\": \"默认业务分类\" }, \"status\": \"SIGNING\", \"expireTime\": \"2023-12-02 00:00:00\", \"publishTime\": \"2023-11-02 16:03:54\" }, { \"id\": \"3151425244519006564\", \"subject\": \"2023年晨光低温合同模板\", \"description\": \"\", \"sn\": \"202310160000001\", \"tenantName\": \"深圳市晨光乳业有限公司\", \"ordinal\": true, \"category\": { \"id\": \"3151379140272197664\", \"name\": \"默认业务分类\" }, \"status\": \"RECALLED\", \"expireTime\": \"2023-11-30 00:00:00\", \"publishTime\": \"2023-10-16 14:38:50\" } ], \"totalCount\": \"12\" }, \"code\": 0, \"message\": \"SUCCESS\" }";
//        JsonNode jsonNode = JSONUtil.readNode(jsonStr);
//        List<FieldMappingBean> list = new ArrayList<>();
//        list.add(new FieldMappingBean("code", null, "code", null, null, null));
//        list.add(new FieldMappingBean("message", null, "message", null, null, null));
//        list.add(new FieldMappingBean("data.id", null, "result.list.id", null, null, null));
//        list.add(new FieldMappingBean("data.subject", null, "result.list.subject", null, null, null));
//        list.add(new FieldMappingBean("data.sn", null, "result.list.sn", null, null, null));
//        list.add(new FieldMappingBean("data.categoryName", null, "result.list.category.name", null, null, null));
//        list.add(new FieldMappingBean("data.categoryId", null, "result.list.category.id", null, null, null));


//        String jsonStr = "{ \"success\": true, \"message\": \"操作成功！\", \"code\": 200, \"result\": [ { \"name\": \"通告类型\", \"code\": \"msg_category\", \"items\": [ { \"value\": \"1\", \"text\": \"通知公告\", \"description\": null, \"sortOrder\": 1, \"title\": \"通知公告\" }, { \"value\": \"2\", \"text\": \"系统消息\", \"description\": null, \"sortOrder\": 1, \"title\": \"系统消息\" } ] }, { \"name\": \"开关\", \"code\": \"is_open\", \"items\": [ { \"value\": \"Y\", \"text\": \"是\", \"description\": null, \"sortOrder\": 1, \"title\": \"是\" }, { \"value\": \"N\", \"text\": \"否\", \"description\": null, \"sortOrder\": 1, \"title\": \"否\" } ] } ], \"timestamp\": 1699498826052 }";
//        JsonNode jsonNode = JSONUtil.readNode(jsonStr);
//        List<FieldMappingBean> list = new ArrayList<>();
//        list.add(new FieldMappingBean("success1", null, "success", null));
//        list.add(new FieldMappingBean("success2", "1", null, null));
//        list.add(new FieldMappingBean("message1", null, "message", null));
//        list.add(new FieldMappingBean("code1", null, "code", null));
//        list.add(new FieldMappingBean("data.name", null, "result.name", null));
//        list.add(new FieldMappingBean("data.code", null, "result.code", null));
//        list.add(new FieldMappingBean("data.items.value", null, "result.items.value", null));
//        list.add(new FieldMappingBean("data.items.text", null, "result.items.text", null));
//        list.add(new FieldMappingBean("user.data.info.value", null, "result.items.value", null));
//        list.add(new FieldMappingBean("user.data.info.text", null, "result.items.text", null));


//        JsonNode jsonNode =null;
//        List<FieldMappingBean> list = new ArrayList<>();
//        list.add(new FieldMappingBean("selectOffset", "0", null, null));
//        list.add(new FieldMappingBean("selectLimit", "10000", null, null));
//        list.add(new FieldMappingBean("createTimeOrder", "desc", null, null));

        JsonNode jsonNode = null;
        List<FieldMappingBean> list = new ArrayList<>();
        list.add(new FieldMappingBean("contractId", "0", null, null,  EnumFieldFormat.jsonObject.getType(),  EnumFieldFormat.jsonObject.getType()));
        list.add(new FieldMappingBean("downloadItems", "ATTACHMENT,CONTRACT", null, null,  EnumFieldFormat.jsonArray.getType(), EnumFieldFormat.jsonArray.getType()));

        List<FieldMappingTree> fieldMappingTrees = toFieldMappingTree(list);
        System.out.println(fieldMappingTrees);
        Map map = buildMap(jsonNode, fieldMappingTrees);
        System.out.println(JSONUtil.toJsonStr(map));
    }


}